package com.xlh.openai.controller;

import cn.hutool.core.util.StrUtil;
import com.xlh.openai.common.Result;
import com.xlh.openai.config.WxMpConfiguration;
import com.xlh.openai.entity.RoleEntity;
import com.xlh.openai.entity.WechatUserEntity;
import com.xlh.openai.exception.ServiceException;
import com.xlh.openai.handler.MenuHandler;
import com.xlh.openai.service.RoleService;
import com.xlh.openai.service.WechatUserService;
import com.xlh.openai.service.impl.WechatUserServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.menu.WxMenu;
import me.chanjar.weixin.common.bean.menu.WxMenuButton;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateIndustry;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateIndustryEnum;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author chufangzheng
 */
@Api(tags = "微信APi")
@RestController
@RequestMapping("wechat")
@Slf4j
public class WechatController {

    @Autowired
    private WxMpService wxMpService;
    @Autowired
    private WxMpMessageRouter messageRouter;
    @Autowired
    private WechatUserService wechatUserService;

    @Value("${menu-url}")
    private String menuUrl;

    @Value("${exchange-url}")
    private String exchangeUrl;

    @Value("${chat-url}")
    private String chatUrl;

    @Autowired
    private RoleService roleService;


    @ApiOperation("微信服务器授权GET")
    @GetMapping(produces = "text/plain;charset=utf-8")
    public String authGet(@RequestParam(name = "signature", required = false) String signature,
                          @RequestParam(name = "timestamp", required = false) String timestamp,
                          @RequestParam(name = "nonce", required = false) String nonce,
                          @RequestParam(name = "echostr", required = false) String echostr) {

        log.info("\n接收到来自微信服务器的认证消息：[{}, {}, {}, {}]", signature,
                timestamp, nonce, echostr);
        if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) {
            throw new IllegalArgumentException("请求参数非法，请核实!");
        }
        if (wxMpService.checkSignature(timestamp, nonce, signature)) {
            return echostr;
        }

        return "非法请求";
    }

    @ApiOperation("微信服务器授权POST")
    @PostMapping(produces = "application/xml; charset=UTF-8")
    public String post( @RequestBody String requestBody,
                        @RequestParam("signature") String signature,
                        @RequestParam("timestamp") String timestamp,
                        @RequestParam("nonce") String nonce,
                        @RequestParam("openid") String openid,
                        @RequestParam(name = "encrypt_type", required = false) String encType,
                        @RequestParam(name = "msg_signature", required = false) String msgSignature) {
        log.info("\n接收微信请求：[openid=[{}], [signature=[{}], encType=[{}], msgSignature=[{}],"
                        + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
                openid, signature, encType, msgSignature, timestamp, nonce, requestBody);

        String appid = wxMpService.getWxMpConfigStorage().getAppId();
        if (!this.wxMpService.switchover(appid)) {
            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置，请核实！", appid));
        }

        if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
            throw new IllegalArgumentException("非法请求，可能属于伪造的请求！");
        }

        String out = null;
        if (encType == null) {
            // 明文传输的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
            WxMpXmlOutMessage outMessage = this.route(inMessage);
            if (outMessage == null) {
                return "";
            }

            out = outMessage.toXml();
        } else if ("aes".equalsIgnoreCase(encType)) {
            // aes加密的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxMpService.getWxMpConfigStorage(),
                    timestamp, nonce, msgSignature);
            log.debug("\n消息解密后内容为：\n{} ", inMessage.toString());
            WxMpXmlOutMessage outMessage = this.route(inMessage);
            if (outMessage == null) {
                return "";
            }

            out = outMessage.toEncryptedXml(wxMpService.getWxMpConfigStorage());
        }

        log.debug("\n组装回复信息：{}", out);
        return out;
    }

    private WxMpXmlOutMessage route(WxMpXmlMessage message) {
        try {
            return this.messageRouter.route(message);
        } catch (Exception e) {
            log.error("路由消息时出现异常！", e);
        }

        return null;
    }

    @ApiOperation("创建菜单")
    @GetMapping("/create")
    public String menuCreateSample(String appid) throws WxErrorException{
        WxMenu menu = new WxMenu();
        // 你问我答button
        WxMenuButton roleButton = new WxMenuButton();
        roleButton.setName("你问我答");
        List<RoleEntity> list = roleService.list();

        for (int i = 0; i < list.size(); i++) {
            RoleEntity roleEntity = list.get(i);
            WxMenuButton innerButton = new WxMenuButton();
            innerButton.setType(WxConsts.MenuButtonType.VIEW);
            innerButton.setName(roleEntity.getName());
            innerButton.setUrl(StrUtil.format(chatUrl, roleEntity.getId()));
            roleButton.getSubButtons().add(innerButton);
        }
        menu.getButtons().add(roleButton);
        //  提问次数button
        WxMenuButton questionTimeButton = new WxMenuButton();
        questionTimeButton.setName("提问次数");
        questionTimeButton.getSubButtons()
                .add(getWxMenuButton( WxConsts.MenuButtonType.CLICK, "次数查询", MenuHandler.QUESTION_SEARCH, null ));
        questionTimeButton.getSubButtons()
                .add(getWxMenuButton(WxConsts.MenuButtonType.VIEW, "充值额度", null, menuUrl));
        questionTimeButton.getSubButtons()
                .add(getWxMenuButton(WxConsts.MenuButtonType.VIEW, "商品兑换", null, exchangeUrl));
        menu.getButtons().add(questionTimeButton);

        this.wxMpService.switchover(appid);
        return this.wxMpService.getMenuService().menuCreate(menu);
    }

    @NotNull
    private WxMenuButton getWxMenuButton( String buttonType, String buttonName, String  buttonKey , String buttonUrl) {
        WxMenuButton button = new WxMenuButton();
        button.setType(buttonType);
        button.setName(buttonName);
        if( StrUtil.isNotBlank(buttonKey) ){
            button.setKey(buttonKey);
        }
        if(StrUtil.isNotBlank(buttonUrl)){
            button.setUrl(buttonUrl);
        }
        return button;
    }

    @ApiOperation("微信登陆授权")
    @GetMapping(value = "auth")
    public Result auth(String code, HttpSession session) {
        // 登陆成功不进行二次登陆
        Object userIdObj = session.getAttribute(WechatUserServiceImpl.SESSION_USERID_KEY);
        Object openIdObj = session.getAttribute(WechatUserServiceImpl.SESSION_USERID_KEY);
        if( userIdObj != null && openIdObj != null ){
            return Result.success();
        }
        try {
            WxOAuth2AccessToken wxOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code);
            String openId = wxOAuth2AccessToken.getOpenId();
            WechatUserEntity wechatUserEntity = wechatUserService.getByOpenId(openId);
            if(wechatUserEntity == null){
                // 如果没有重新初始化用户
                wechatUserEntity = new WechatUserEntity();
                wechatUserEntity.setOpenid(openId);
                wechatUserEntity.setCreateTime(new Date());
                wechatUserEntity.setUpdateTime(new Date());
                wechatUserService.save(wechatUserEntity);
            }
            // 短暂存储会话ID
            session.setAttribute(WechatUserServiceImpl.SESSION_USERID_KEY, wechatUserEntity.getId());
            session.setAttribute(WechatUserServiceImpl.SESSION_OPENID_KEY, openId);
        }catch (Exception e){
            log.error("d登陆失败：{}" , e);
            throw new ServiceException("登陆失败");
        }
        return Result.success();
    }

    @ApiOperation("发送模板消息测试")
    @GetMapping(value = "sendTemplateMsg")
    public String sendTemplateMsg() throws WxErrorException {

        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                .toUser("or3B-52jZ-YvyOhcVKrd2NlfCGFg")
                .templateId("IOLB_cblwW4k2xq-BgaLrBVWNboulHRouM7X_awjGak")
                .build();
        templateMessage.addData(new WxMpTemplateData("first","您好，您的订单已支付成功！","#000000"));
        templateMessage.addData(new WxMpTemplateData("keyword1","您的订单编号是：8975595","#000080"));
        templateMessage.addData(new WxMpTemplateData("keyword2","感谢您使用的同时也希望您提出宝贵的意见和建议！"));
        templateMessage.addData(new WxMpTemplateData("keyword3","感谢您使用的同时也希望您提出宝贵的意见和建议！"));
        templateMessage.addData(new WxMpTemplateData("keyword4","感谢您使用的同时也希望您提出宝贵的意见和建议！"));
        templateMessage.addData(new WxMpTemplateData("remark","感谢您使用的同时也希望您提出宝贵的意见和建议！"));

        wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
        return "非法请求";
    }


    @ApiOperation("添加模板信息")
    @GetMapping(value = "addTemplateMsg")
    public Result addTemplateMsg() throws WxErrorException {

        String tempId = wxMpService.getTemplateMsgService().addTemplate(WxMpConfiguration.TEMPLATE_SHORTID);
        System.out.println(tempId);
        return Result.success();
    }

    @ApiOperation("设置所属行业")
    @GetMapping(value = "setIndustry", produces = "text/plain;charset=utf-8")
    public Result setIndustry() throws WxErrorException {
        WxMpTemplateIndustry wxMpIndustry = new WxMpTemplateIndustry();
        wxMpIndustry.setPrimaryIndustry(WxMpTemplateIndustryEnum.E_COMMERCE);
        wxMpIndustry.setSecondIndustry(WxMpTemplateIndustryEnum.IT_SOFTWARE_AND_SERVICES);
        wxMpService.getTemplateMsgService().setIndustry(wxMpIndustry);
        return Result.success();
    }


}
